/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

const express = require('express');
const cors = require('cors');
const cookieParser = require('cookie-parser');
const fs = require('fs');
const path = require('path');

// Creating the Express Server
const app = express();

// Parse JSON request bodies
app.use(express.json());

// Parse URL-encoded request bodies
app.use(express.urlencoded({ extended: true }));

// Parse cookies
app.use(cookieParser());

// Configure CORS to allow cross-origin requests
app.use(cors({
    origin: '*', // allow all origins
    methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
    allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'],
    credentials: true,
    exposedHeaders: ['Content-Type', 'Authorization']
}));

// Load HTML template file once at startup
const templatePath = path.join(__dirname, 'templates', 'headerResponse.html');
let htmlTemplate = '';

try {
    htmlTemplate = fs.readFileSync(templatePath, 'utf-8');
    console.log('HTML template loaded successfully');
} catch (error) {
    console.error('Failed to load HTML template:', error.message);
    // Fallback in case the template file is missing
    htmlTemplate = '<!DOCTYPE html><html><body><h1>Template load failed</h1></body></html>';
}

// HTML escape helper
function escapeHtml(text) {
    const map = {
        '&': '&amp;',
        '<': '&lt;',
        '>': '&gt;',
        '"': '&quot;',
        "'": '&#039;'
    };
    return String(text).replace(/[&<>"']/g, m => map[m]);
}

// Format JSON objects for display
function formatJSON(obj) {
    return JSON.stringify(obj, null, 2);
}

// Get badge color by HTTP method
function getMethodColor(method) {
    const colors = {
        'GET': '#61affe',
        'POST': '#49cc90',
        'PUT': '#fca130',
        'DELETE': '#f93e3e',
        'PATCH': '#50e3c2',
        'OPTIONS': '#9012fe'
    };
    return colors[method] || '#999';
}

// Generate HTML response content
function generateHTMLResponse(req) {
    const method = req.method;
    const headers = req.headers;
    const body = req.body || {};

    // Build header table rows
    function generateHeaderRows() {
        const entries = Object.entries(headers);
        if (entries.length === 0) {
            return '<tr><td class="empty" colspan="2">No headers</td></tr>';
        }

        return entries.map(([key, value]) => `
                <tr>
                    <td class="header-key">${escapeHtml(key)}</td>
                    <td class="header-value">${escapeHtml(value)}</td>
                </tr>
        `).join('');
    }

    // Build request body section when needed
    function generateBodySection() {
        if (Object.keys(body).length === 0) {
            return '';
        }
        return `
        <div class="section">
            <h2 class="section-title">Request Body</h2>
            <div class="body-content">${escapeHtml(formatJSON(body))}</div>
        </div>
        `;
    }

    return htmlTemplate
        .replace(/\{\{METHOD\}\}/g, escapeHtml(method))
        .replace(/\{\{METHOD_COLOR\}\}/g, getMethodColor(method))
        .replace(/\{\{HEADER_ROWS\}\}/g, generateHeaderRows())
        .replace(/\{\{BODY_SECTION\}\}/g, generateBodySection());
}

// Handle all HTTP methods and echo headers
app.all('/api/headers', (req, res) => {
    console.log('Received request:', req.method, req.url);
    console.log('Headers:', req.headers);

    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.send(generateHTMLResponse(req));
});

// Also handle the root path for convenience
app.all('/', (req, res) => {
    console.log('Received root path request:', req.method, req.url);

    res.setHeader('Content-Type', 'text/html; charset=utf-8');
    res.send(generateHTMLResponse(req));
});

// Get local network IP address
function getLocalNetworkIP() {
    const os = require('os');
    const interfaces = os.networkInterfaces();
    for (const name of Object.keys(interfaces)) {
        const iface = interfaces[name];
        if (!iface) {
            continue;
        }
        for (const addr of iface) {
            // Skip internal (loopback) and non-IPv4 addresses
            if (addr.family === 'IPv4' && !addr.internal) {
                return addr.address;
            }
        }
    }
    return '127.0.0.1';
}

// Start server on port 8081
const PORT = 8081;
const localIP = getLocalNetworkIP();
app.listen(PORT, '0.0.0.0', () => {
    console.log(`Header server listening on port ${PORT}`);
    console.log('\n=== Access URLs ===');
    console.log(`Local: http://localhost:${PORT}/api/headers`);
    console.log(`Local: http://127.0.0.1:${PORT}/api/headers`);
    console.log(`Network: http://${localIP}:${PORT}/api/headers`);
    console.log('\n=== Configuration for HarmonyOS App ===');
    console.log(`Use this IP in your app: ${localIP}`);
    console.log(`Full URL: http://${localIP}:${PORT}/api/headers`);
    console.log('\nSupports methods: GET, POST, PUT, DELETE, PATCH, OPTIONS');
    console.log('Responses are rendered as a styled HTML page');
    console.log('\nNote: Ensure your device is on the same local network as this server.');
});